﻿namespace Pub.Class
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Text;

    public static class IDataReaderExtensions
    {
        public static T Get<T>(this IDataReader reader, string field)
        {
            return reader.Get<T>(field, default(T));
        }

        public static T Get<T>(this IDataReader reader, string field, T defaultValue)
        {
            object obj2 = reader[field];
            if (obj2 == DBNull.Value)
            {
                return defaultValue;
            }
            return obj2.ConvertTo<T>(defaultValue);
        }

        public static string ToCSV(this IDataReader dr)
        {
            return dr.ToCSV(',', true);
        }

        public static string ToCSV(this IDataReader dr, char c)
        {
            return dr.ToCSV(c, true);
        }

        public static string ToCSV(this IDataReader dr, char c = ',', bool isClose = true)
        {
            if (dr.IsNull())
            {
                return "";
            }
            StringBuilder builder = new StringBuilder();
            int i = 0;
            int fieldCount = dr.FieldCount;
            while (i < fieldCount)
            {
                builder.AppendFormat("{0}{1}", dr.GetName(i), c);
                i++;
            }
            builder.Remove(builder.Length - 1, 1);
            builder.Append("\n");
            while (dr.Read())
            {
                int num3 = 0;
                int num4 = dr.FieldCount;
                while (num3 < num4)
                {
                    builder.AppendFormat("{0}{1}", dr[num3].ToString(), c);
                    num3++;
                }
                builder.Remove(builder.Length - 1, 1);
                builder.Append("\n");
            }
            if (isClose)
            {
                dr.Close();
                dr.Dispose();
                dr = null;
            }
            return builder.ToString();
        }

        public static string ToDataReaderJson(this IDataReader dr)
        {
            return dr.ToDataReaderJson(true);
        }

        public static string ToDataReaderJson(this IDataReader dr, bool isClose)
        {
            if (dr.IsNull())
            {
                return "[]";
            }
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            while (dr.Read())
            {
                builder.Append("{");
                int i = 0;
                int fieldCount = dr.FieldCount;
                while (i < fieldCount)
                {
                    builder.AppendFormat("\"{0}\":{1},", dr.GetName(i), dr[i].ToJson());
                    i++;
                }
                builder.Remove(builder.Length - 1, 1);
                builder.Append("},");
            }
            if (isClose)
            {
                dr.Close();
                dr.Dispose();
                dr = null;
            }
            if (builder.Length > 1)
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("]");
            return builder.ToString();
        }

        public static DataTable ToDataTable(this IDataReader dr)
        {
            return dr.ToDataTable(true);
        }

        public static DataTable ToDataTable(this IDataReader dr, bool isClose)
        {
            DataTable table = new DataTable();
            if (dr.IsNull())
            {
                return null;
            }
            int fieldCount = dr.FieldCount;
            for (int i = 0; i < fieldCount; i++)
            {
                table.Columns.Add(dr.GetName(i).Replace("_", ""), dr.GetFieldType(i));
            }
            while (dr.Read())
            {
                object[] values = new object[fieldCount];
                dr.GetValues(values);
                table.Rows.Add(values);
            }
            if (isClose)
            {
                dr.Close();
                dr.Dispose();
                dr = null;
            }
            return table;
        }

        public static TResult ToEntity<TResult>(this IDataReader dr) where TResult: class, new()
        {
            return dr.ToList<TResult>().FirstOrDefault<TResult>();
        }

        public static TResult ToEntity<TResult>(this IDataReader dr, bool isClose) where TResult: class, new()
        {
            return dr.ToList<TResult>(isClose).FirstOrDefault<TResult>();
        }

        public static string ToJson(this IDataReader dr)
        {
            return dr.ToDataReaderJson(true);
        }

        public static string ToJson(this IDataReader dr, bool isClose)
        {
            return dr.ToDataReaderJson(isClose);
        }

        public static string ToJson(this IDataReader dr, params string[] fields)
        {
            return dr.ToJson(fields, null);
        }

        public static string ToJson(this IDataReader dr, string[] fields, string[] alias)
        {
            if (dr.IsNull())
            {
                return "[]";
            }
            if (alias.IsNull() || (fields.Length != alias.Length))
            {
                alias = fields;
            }
            if (fields.IsNull() || (fields.Length == 0))
            {
                return dr.ToJson();
            }
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            while (dr.Read())
            {
                builder.Append("{");
                int index = 0;
                int length = fields.Length;
                while (index < length)
                {
                    builder.AppendFormat("\"{0}\":{1},", alias[index], dr[fields[index]].ToJson());
                    index++;
                }
                builder.Remove(builder.Length - 1, 1);
                builder.Append("},");
            }
            dr.Close();
            dr.Dispose();
            dr = null;
            if (builder.Length > 1)
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("]");
            return builder.ToString();
        }

        public static List<TResult> ToList<TResult>(this IDataReader dr) where TResult: class, new()
        {
            return dr.ToList<TResult>(true);
        }

        public static List<TResult> ToList<TResult>(this IDataReader dr, bool isClose) where TResult: class, new()
        {
            List<TResult> list = new List<TResult>();
            if (!dr.IsNull())
            {
                IDataReaderEntityBuilder<TResult> builder = IDataReaderEntityBuilder<TResult>.CreateBuilder(dr);
                while (dr.Read())
                {
                    list.Add(builder.Build(dr));
                }
                if (isClose)
                {
                    dr.Close();
                    dr.Dispose();
                    dr = null;
                }
            }
            return list;
        }

        public static List<TResult> ToList2<TResult>(this IDataReader dr) where TResult: class, new()
        {
            return dr.ToList2<TResult>(true);
        }

        public static List<TResult> ToList2<TResult>(this IDataReader dr, bool isClose) where TResult: class, new()
        {
            List<string> drColumns;
            List<PropertyInfo> prlist;
            List<TResult> list = new List<TResult>();
            if (!dr.IsNull())
            {
                drColumns = new List<string>();
                int fieldCount = dr.FieldCount;
                for (int i = 0; i < fieldCount; i++)
                {
                    drColumns.Add(dr.GetName(i).Trim());
                }
                prlist = new List<PropertyInfo>();
                Type type = typeof(TResult);
                Array.ForEach<PropertyInfo>(type.GetPropertiesCache(), delegate (PropertyInfo p) {
                    if (drColumns.IndexOf(p.Name) != -1)
                    {
                        prlist.Add(p);
                    }
                });
                while (dr.Read())
                {
                    TResult ob = Activator.CreateInstance<TResult>();
                    prlist.ForEach(delegate (PropertyInfo p) {
                        if (dr[p.Name] != DBNull.Value)
                        {
                            p.SetValue(ob, dr[p.Name], null);
                        }
                    });
                    list.Add(ob);
                }
                if (isClose)
                {
                    dr.Close();
                    dr.Dispose();
                    dr = null;
                }
            }
            return list;
        }

        public static List<TResult> ToList3<TResult>(this IDataReader dr) where TResult: class, new()
        {
            return dr.ToList3<TResult>(true);
        }

        public static List<TResult> ToList3<TResult>(this IDataReader dr, bool isClose) where TResult: class, new()
        {
            List<TResult> list = new List<TResult>();
            if (!dr.IsNull())
            {
                int fieldCount = dr.FieldCount;
                while (dr.Read())
                {
                    TResult local = Activator.CreateInstance<TResult>();
                    for (int i = 0; i < fieldCount; i++)
                    {
                        if (!dr[i].IsNull() && !string.IsNullOrEmpty(dr[i].ToString()))
                        {
                            local.GetType().GetPropertyCache(dr.GetName(i).Trim()).SetValue(local, dr[i], null);
                        }
                    }
                    list.Add(local);
                }
                if (isClose)
                {
                    dr.Close();
                    dr.Dispose();
                    dr = null;
                }
            }
            return list;
        }
    }
}

